package com.learning.spring.ioc.container;

import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;

/**
 * ClassName: BeanFactoryContainer
 * Description: BeanFactory，提供高级Ioc 的配置机制
 * BeanFactory 是Spring 框架的基础设施，面向 Spring 本身
 * Date: 2018/7/26 14:45 【需求编号】
 *
 * @author Sam Sho
 * @version V1.0.0
 */
public class ContainerBeanFactory {

    public static void main(String[] args) {
        test2();
    }


    /**
     * BeanFactory 的类体系结构
     * <p>
     * 1. BeanFactory：主要方法是getBean，功能通过其他接口得到扩展，如：
     * 2. ListableBeanFactory：访问容器中Bean 基本信息的若干方法，如查看Bean的个数（getBeanDefinitionCount），获取某一类型 Bean 的配置名称（getBeanNamesForType）
     * 3. HierarchicalBeanFactory：父子层级关联的容器体系，子容器可以通过接口方法访问父容器。如 Spring MVC 展现层位于子容器中，业务层和持久层位于父容器中
     * 4. ConfigurableBeanFactory：重要接口。增强了Ioc 容器的可定制型
     * 5. AutowireCapableBeanFactory：定义装配方法
     * 6. SingletonBeanRegistry：定义了允许在运行期向容器注册单实例Bean的方法
     * 7. BeanDefinitionRegistry：spring配置文件中每一个<Bean>节点元素在spring容器里都通过一个 BeanDefinition 对象表示，
     * 它描述了Bean的配置信息。而 BeanDefinitionRegistry 接口提供了先容器手工注册 BeanDefinition 对象的方法
     */
    static void test() {
    }

    /**
     * 初始化 BeanFactory 容器：通过 DefaultListableBeanFactory 、XmlBeanDefinitionReader 实现。
     * 原来的 XmlBeanFactory 已经废弃
     * <p>
     * 1. BeanFactory 容器初始化的时候，不会实例化bean，第一次访问Bean才实例化
     */
    static void test2() {
        ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
        // 使用 ClassPathContextResource
        Resource resource = resolver.getResource("spring-context.xml");

        // XmlBeanFactory factory = new XmlBeanFactory(resource); 废弃，不用
        DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
        XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(factory);
        reader.loadBeanDefinitions(resource);

        System.out.println("BeanFactory 容器初始化完成，但是没有实例化bean");

        BeanContainer beanContainer = factory.getBean("beanContainer", BeanContainer.class);
        beanContainer.done();

        // 对于单例（singleton）的Bean来说，会做缓存，锁着第二次 getBean 的时候直接从容器中获取
        // 在 DefaultSingletonBeanRegistry 类中提供了一个用于缓存单实例（singleton）的缓存器，是Map实现的。
        beanContainer = factory.getBean("beanContainer", BeanContainer.class);
        beanContainer.done();

        /*
        BeanFactory 容器初始化完成，但是没有实例化bean
        BeanContainerImpl 被实例化了
        BeanContainerImpl.do() 方法被调用~~
        BeanContainerImpl.do() 方法被调用~~
        */
    }

    /**
     * HierarchicalBeanFactory 接口，父子层级关联的容器体系，子容器可以通过接口方法访问父容器。
     * 如 Spring MVC 展现层位于子容器中，业务层和持久层位于父容器中
     */
    static void test3() {

    }


}
